package cfig.launcher

import cfig.helper.Helper.Companion.check_call
import cfig.ota.UpdatePkgAB
import cfig.ota.UpdatePkgRecovery
import java.io.File
import cfig.toolset.AdbTool
import org.slf4j.LoggerFactory
import se.vidstige.jadb.JadbConnection
import se.vidstige.jadb.JadbDevice
import java.net.MalformedURLException
import java.net.URI
import java.net.URISyntaxException
import java.net.URL
import java.util.*
import kotlin.system.exitProcess

class Updater {
    private var dut: JadbDevice? = null
    private val log = LoggerFactory.getLogger(Updater::class.java)
    private var adbTool = AdbTool()
    private var exitValue = 0

    fun setUp(): Updater {
        val jadb = JadbConnection()
        when (jadb.devices.size) {
            0 -> {
                log.error("No device connected")
                exitProcess(1)
            }
            1 -> dut = jadb.devices[0]
            else -> {
                log.error("Must have only 1 device connected")
                println("Device List:")
                for (i in 0 until jadb.devices.size) {
                    println("\t" + i.toString() + ": " + jadb.devices[i].serial)
                }
                print("Please choose: ")
                val sc = Scanner(System.`in`)
                val userChoice = sc.nextInt()
                log.info("You selected: $userChoice")
                if (userChoice in 0 until jadb.devices.size) {
                    dut = jadb.devices[userChoice]
                } else {
                    exitProcess(1)
                }
            }
        }
        if ((dut!!.state != JadbDevice.State.Device)) {
            log.error("device [" + dut!!.serial + "(" + dut!!.state + ")] unavailable")
            exitProcess(1)
        }
        if (!adbTool.checkCall(dut!!, "root")) {
            log.error("adb root is required")
            exitProcess(1)
        }
        return this
    }

    private fun isValidURL(url: String): Boolean {
        try {
            val inUri = URL(url).toURI()
        } catch (e: MalformedURLException) {
            return false
        } catch (e: URISyntaxException) {
            return false
        }
        return true
    }

    @ExperimentalStdlibApi
    fun install(updatePkgURL: String): Updater {
        var localFile = updatePkgURL
        var canonicalURI: String? = null
        when {
            isValidURL(updatePkgURL) -> {
                "wget $updatePkgURL --quiet -O down.zip".check_call()
                localFile = "down.zip"
                canonicalURI = URL(updatePkgURL).toURI().toString()
            }
            File(updatePkgURL).exists() -> {
                //pass
            }
            else -> {
                log.error("Target file [$updatePkgURL] invalid")
                exitProcess(3)
            }
        }

        if (adbTool.getProp(dut!!, "ro.build.ab_update") == "true") {//AB
            exitValue = UpdatePkgAB(localFile, canonicalURI).installTo(dut!!)
        } else {
            UpdatePkgRecovery(localFile).installTo(dut!!)
        }
        return this
    }

    fun postInstall(): Updater {
        File("down.zip").let {
            if (it.exists()) {
                log.info("Deleting ${it.name}")
                it.delete()
            }
        }
        return this
    }

    companion object {
        @OptIn(ExperimentalStdlibApi::class)
        fun main(args: Array<String>) {
            Updater()
                    .setUp()
                    .install(args[0])
                    .postInstall()
        }
    }
}
